<script setup lang="ts">
import {
  useMessage,
  NButton,
  NSpace,
  NDataTable,
  NInput,
  type DataTableColumns,
  NPagination,
  NDatePicker,
  NTreeSelect
} from 'naive-ui'
import { computed, onMounted, reactive, ref } from 'vue'
import { subDays, format } from 'date-fns'
import { sendRequest } from '@/utils/api'
import type { LogModel } from '@/api/log'
import type { HttpResponse, HttpResponsePagination } from '@/utils/http'
import TableView from '@/components/TableView.vue'
import type { DicTreeModel } from '@/api/dic'
import { LogType, Handles } from '@/enums/system'
import { unescape } from 'lodash-es'

type Reset = () => void

function useQueryForm<T = unknown>(form: T, reset: Reset): [form: T, reset: Reset] {
  return [form, reset]
}

const message = useMessage()
const [form, resetForm] = useQueryForm(
  reactive({
    startTime: format(subDays(Date.now(), 1), 'yyyy-MM-dd HH:mm:ss'),
    endTime: format(Date.now(), 'yyyy-MM-dd HH:mm:ss'),
    logType: null,
    loginName: null,
    key: null
  }),
  () => {
    form.startTime = format(subDays(Date.now(), 1), 'yyyy-MM-dd HH:mm:ss')
    form.endTime = format(Date.now(), 'yyyy-MM-dd HH:mm:ss')
    form.logType = null
    form.loginName = null
    form.key = null
  }
)
const datetime = computed<[string, string]>({
  get() {
    return [form.startTime, form.endTime]
  },
  set(v) {
    form.startTime = v[0]
    form.endTime = v[1]
  }
})
const tableData = ref<LogModel[]>([])
const paginationReactive = reactive({
  page: 1,
  pageSize: 10,
  showSizePicker: true,
  pageSizes: [10, 20, 50, 100, 500],
  itemCount: 0,
  onChange: (page: number) => {
    paginationReactive.page = page
    queryTableData()
  },
  onUpdatePageSize: (pageSize: number) => {
    paginationReactive.pageSize = pageSize
    paginationReactive.page = 1
    queryTableData()
  }
})
const columns: DataTableColumns<LogModel> = [
  {
    fixed: 'left',
    title: '序号',
    key: 'orderIndex',
    render: (_, i) => {
      return ++i + (paginationReactive.page - 1) * paginationReactive.pageSize
    },
    width: 70,
    align: 'center'
  },
  {
    fixed: 'left',
    title: '客户端IP',
    key: 'clientIp',
    align: 'center',
    width: 120
  },
  {
    title: '登录名',
    key: 'loginName',
    align: 'center',
    width: 100
  },
  {
    title: '日志内容',
    key: 'logContent',
    align: 'center',
    maxWidth: 240,
    ellipsis: {
      tooltip: {
        contentStyle: {
          maxWidth: '400px'
        }
      }
    }
  },
  {
    title: '日志类型',
    key: 'logType',
    align: 'center',
    width: 100,
    render: (e) => getRowType(logTypeSelectOptions.value, e.logType)
  },
  {
    title: '操作类型',
    key: 'operateType',
    align: 'center',
    width: 100,
    render: (e) => getRowType(handlesTypeOptions.value, e.operateType)
  },
  {
    title: '请求类名',
    key: 'className',
    maxWidth: 240,
    minWidth: 240,
    ellipsis: {
      tooltip: {
        contentStyle: {
          maxWidth: '400px'
        }
      }
    }
  },
  {
    title: '请求方法',
    key: 'method',
    maxWidth: 240,
    minWidth: 240,
    align: 'center',
    ellipsis: {
      tooltip: {
        contentStyle: {
          maxWidth: '400px'
        }
      }
    }
  },
  {
    title: '请求参数',
    key: 'params',
    maxWidth: 240,
    minWidth: 240,
    ellipsis: {
      tooltip: {
        contentStyle: {
          maxWidth: '400px'
        }
      }
    },
    render: (e) => unescape(e.params)
  },
  {
    title: '执行时长（s）',
    key: 'time',
    align: 'center'
  },
  {
    fixed: 'right',
    title: '创建时间',
    key: 'createTime',
    align: 'center',
    width: 200
  }
]

// 获取数据列表
const tableLoading = ref(false)
const queryTableData = async (resetPage = false) => {
  if (resetPage) paginationReactive.page = 1
  tableLoading.value = true
  const [error, res] = await sendRequest<HttpResponsePagination<LogModel>>({
    module: 'log',
    api: 'list',
    override: {
      params: {
        ...form,
        page: paginationReactive.page,
        limit: paginationReactive.pageSize
      }
    }
  })
  tableLoading.value = false

  if (error) return message.error(error.message)
  paginationReactive.itemCount = res.data.totalCount
  tableData.value = res.data.list
}

// 日志类型
const logTypeSelectOptions = ref<DicTreeModel[] | undefined>()
const queryLogType = async () => {
  const [error, res] = await sendRequest<HttpResponse<DicTreeModel[]>>({
    module: 'dic',
    api: 'getTree',
    override: {
      params: {
        dicCode: LogType.Parent
      }
    }
  })

  if (error) return message.error(error.message)
  if (res.code !== 0) return message.error(res.msg)
  logTypeSelectOptions.value = res.data[0].children
}
const handlesTypeOptions = ref<DicTreeModel[] | undefined>()
const queryHandlesType = async () => {
  const [error, res] = await sendRequest<HttpResponse<DicTreeModel[]>>({
    module: 'dic',
    api: 'getTree',
    override: {
      params: {
        dicCode: Handles.Parent
      }
    }
  })

  if (error) return message.error(error.message)
  if (res.code !== 0) return message.error(res.msg)
  handlesTypeOptions.value = res.data[0].children
}

const getRowType = (dicTree: DicTreeModel[] | undefined, id: number) => {
  if (!dicTree) return ''
  const target = dicTree.find((e) => e.id === id)
  return target ? target.name : ''
}

onMounted(() => {
  queryLogType()
  queryHandlesType()
  queryTableData()
})
</script>

<template>
  <TableView>
    <template #form>
      <NSpace style="padding: 2px 0">
        <NDatePicker input-readonly
          v-model:formatted-value="datetime"
          value-format="yyyy-MM-dd HH:mm:ss"
          type="datetimerange"
          default-time="00:00:00"
          size="small"
        />
        <NTreeSelect
          v-model:value="form.logType"
          size="small"
          clearable
          filterable
          placeholder="日志类型"
          :options="logTypeSelectOptions"
          key-field="id"
          label-field="name"
        />
        <NInput
          v-model:value="form.loginName"
          clearable
          size="small"
          placeholder="登录名"
        />
        <NInput
          v-model:value="form.key"
          clearable
          size="small"
          placeholder="日志内容关键词"
        />
        <NButton
          @click="queryTableData(true)"
          :disabled="tableLoading"
          :loading="tableLoading"
        >
          查询
        </NButton>
        <NButton
          @click="resetForm"
          ghost
        >
          重置
        </NButton>
      </NSpace>
    </template>
    <template #table="props">
      <n-data-table
        v-bind="props"
        :data="tableData"
        :columns="columns"
        :loading="tableLoading"
        size="small"
        bordered
      />
    </template>
    <template #pagination>
      <NSpace justify="end">
        <NPagination
          size="small"
          show-size-picker
          show-quick-jumper
          :page-sizes="paginationReactive.pageSizes"
          :item-count="paginationReactive.itemCount"
          :page="paginationReactive.page"
          :page-size="paginationReactive.pageSize"
          @update:page="paginationReactive.onChange"
          @update:page-size="paginationReactive.onUpdatePageSize"
        >
          <template #prefix>共{{ paginationReactive.itemCount }}条</template>
        </NPagination>
      </NSpace>
    </template>
  </TableView>
</template>
